package com.yuda.afterexamscore.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.math.MathUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.yuda.afterexamscore.domain.SystemVariables;
import com.yuda.afterexamscore.domain.ThQuesScoreMapping;
import com.yuda.afterexamscore.service.IThQuesScoreMappingService;
import com.yuda.afterexamscore.service.ITsinghuaFormalAnswerService;
import com.yuda.afterexamscore.service.SpotCheckAnswerService;
import com.yuda.afterexamscore.vo.RedisErr;
import com.yuda.afterexamscore.vo.TsinghuaFormalAnswerVo;
import com.yuda.common.core.web.controller.BaseController;
import com.yuda.common.core.web.domain.AjaxResult;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;

import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * 清华管理机学生答案Controller
 *
 * @author fmx
 * @date 2021-05-12
 */
@RestController
@RequestMapping("/formalAnswer")
@RefreshScope
public class TsinghuaFormalAnswerController extends BaseController {
    @Autowired
    private ITsinghuaFormalAnswerService tsinghuaFormalAnswerService;

    @Autowired
    private IThQuesScoreMappingService thQuesScoreMappingService;

    @Autowired
    private SpotCheckAnswerService spotCheckAnswerService;

    private static Logger log = LoggerFactory.getLogger(TsinghuaFormalAnswerController.class);

    private static Queue<TsinghuaFormalAnswerVo> tsinghuaFormalAnswerQueue = new ConcurrentLinkedQueue<>();

    private static String examUuid;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Value("${examUUID}")
    private String examUUID;

    private static Float process = 0f;

//    /**
//     * 查询清华管理机学生答案列表
//     */
//    @PreAuthorize(hasPermi = "afterexamscore:answer:list")
//    @GetMapping("/list")
//    public TableDataInfo list(TsinghuaFormalAnswer tsinghuaFormalAnswer)
//    {
//        startPage();
//        List<TsinghuaFormalAnswer> list = tsinghuaFormalAnswerService.selectTsinghuaFormalAnswerList(tsinghuaFormalAnswer);
//        return getDataTable(list);
//    }
//
//    /**
//     * 导出清华管理机学生答案列表
//     */
//    @PreAuthorize(hasPermi = "afterexamscore:answer:export")
//    @Log(title = "清华管理机学生答案", businessType = BusinessType.EXPORT)
//    @PostMapping("/export")
//    public void export(HttpServletResponse response, TsinghuaFormalAnswer tsinghuaFormalAnswer) throws IOException
//    {
//        List<TsinghuaFormalAnswer> list = tsinghuaFormalAnswerService.selectTsinghuaFormalAnswerList(tsinghuaFormalAnswer);
//        ExcelUtil<TsinghuaFormalAnswer> util = new ExcelUtil<TsinghuaFormalAnswer>(TsinghuaFormalAnswer.class);
//        util.exportExcel(response, list, "answer");
//    }
//
//    /**
//     * 获取清华管理机学生答案详细信息
//     */
//    @PreAuthorize(hasPermi = "afterexamscore:answer:query")
//    @GetMapping(value = "/{id}")
//    public AjaxResult getInfo(@PathVariable("id") Integer id)
//    {
//        return AjaxResult.success(tsinghuaFormalAnswerService.selectTsinghuaFormalAnswerById(id));
//    }
//
//    /**
//     * 新增清华管理机学生答案
//     */
//    @PreAuthorize(hasPermi = "afterexamscore:answer:add")
//    @Log(title = "清华管理机学生答案", businessType = BusinessType.INSERT)
//    @PostMapping
//    public AjaxResult add(@RequestBody TsinghuaFormalAnswer tsinghuaFormalAnswer)
//    {
//        return toAjax(tsinghuaFormalAnswerService.insertTsinghuaFormalAnswer(tsinghuaFormalAnswer));
//    }
//
//    /**
//     * 修改清华管理机学生答案
//     */
//    @PreAuthorize(hasPermi = "afterexamscore:answer:edit")
//    @Log(title = "清华管理机学生答案", businessType = BusinessType.UPDATE)
//    @PutMapping
//    public AjaxResult edit(@RequestBody TsinghuaFormalAnswer tsinghuaFormalAnswer)
//    {
//        return toAjax(tsinghuaFormalAnswerService.updateTsinghuaFormalAnswer(tsinghuaFormalAnswer));
//    }
//
//    /**
//     * 删除清华管理机学生答案
//     */
//    @PreAuthorize(hasPermi = "afterexamscore:answer:remove")
//    @Log(title = "清华管理机学生答案", businessType = BusinessType.DELETE)
//	@DeleteMapping("/{ids}")
//    public AjaxResult remove(@PathVariable Integer[] ids)
//    {
//        return toAjax(tsinghuaFormalAnswerService.deleteTsinghuaFormalAnswerByIds(ids));
//    }


    /**
     * 填空题答案插入答案穷举表
     */
    @PostMapping("/tianKongInsertThQuesScoreMapping")
    @ApiOperation("学生填空题答案插入答案穷举表")
    public void tianKongInsertThQuesScoreMapping(@RequestParam(value = "relationSubjectId", required = false) String subjectId) throws InterruptedException {
        process = 0f;
        //将之前的错误都删除
        redisTemplate.delete(examUUID + "TsinghuaFormalAnswerErr");
        //2021年6月9日新增，添加一个开关，让死锁接口只能存在一个
        SystemVariables.InterfaceSwitch = false;
        SystemVariables.msg = "填空题答案插入答案穷举表中，请稍等";
        try {
            //清空队列
            tsinghuaFormalAnswerQueue.clear();
            //查找examUuid
            examUuid = tsinghuaFormalAnswerService.findExamUuid();
            process = 20f;
            //更新Tsinghua_formal_answer字段
            //更新题目相关信息
            jdbcTemplate.update("UPDATE \n" +
                    "tsinghua_formal_answer a,dp_ques_index_mapping b \n" +
                    "set \n" +
                    "a.ques_index = b.ques_index, \n" +
                    "a.right_answer = b.right_answer,\n" +
                    "a.full_score = b.full_score\n" +
                    "where a.ques_id = b.question_id ");
            process = 40f;
            //查询出所有答案已排除穷举表已有数据
            List<TsinghuaFormalAnswerVo> tsinghuaFormalAnswerVos = tsinghuaFormalAnswerService.queryAllCompletionAnswers(subjectId);
            System.out.println("wait");
            //插入队列
            tsinghuaFormalAnswerQueue.addAll(tsinghuaFormalAnswerVos);
            process = 60f;
        } catch (Exception e) {
            insertTsinghuaFormalAnswerErr("未知错误，请查看日志");
            process = 0f;
            SystemVariables.InterfaceSwitch = true;
            e.printStackTrace();
        }
        //瓜分线程,每个线程处理100条数据
        int threadNum = (int) Math.ceil(tsinghuaFormalAnswerQueue.size() / 100) + 1;
        if (threadNum >= 1) {
            CountDownLatch latch = new CountDownLatch(threadNum);
            ExecutorService executor = Executors.newFixedThreadPool(100);
            if (threadNum > 0) {
                for (int i = 0; i < threadNum; i++) { // 开threadNum个线程
                    Runnable task = new TsinghuaFormalAnswerController.MultithreadingOfTianKongInsert(latch);
                    // 执行
                    executor.execute(task);
                }
            }
            latch.await(); //
            executor.shutdown();//关闭线程池
        }
        process = 100f;
        //最后打开开关
        SystemVariables.InterfaceSwitch = true;
    }

    /**
     * 多线程算分,根据答案穷举表更新score
     */
    @PutMapping("/updateScore/{subjectIds}")
    @ApiOperation("多线程算分,根据答案穷举表更新score,需要一些时间,使用中!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
//    @PreAuthorize(hasRole = "admin")
    public void updateScore(@PathVariable String[] subjectIds) throws InterruptedException {
        process = 0f;
        //将之前的错误都删除
        redisTemplate.delete(examUUID + "TsinghuaFormalAnswerErr");
        //2021年6月9日新增，添加一个开关，让死锁接口只能存在一个
        //如果能通行，关闭开关
        SystemVariables.InterfaceSwitch = false;
        SystemVariables.msg = "根据答案穷举表更新formal_answer的score字段中，请稍等";
        //重新运行重置三张表状态
        for (String subject : subjectIds) {
            redisTemplate.opsForHash().put(examUUID + "ProcessOf" + subject, "formalAnswer", "0");
            redisTemplate.opsForHash().put(examUUID + "ProcessOf" + subject, "quesScore", "0");
            redisTemplate.opsForHash().put(examUUID + "ProcessOf" + subject, "subjectScore", "0");
        }
        process = 5f;
        //计算时间:初始时间
        Instant insOne = Instant.now();
        //更新表字段,先判断有没有更新,没有则更新
        try {
            StringBuilder stringBuilder = new StringBuilder();
            Arrays.stream(subjectIds).forEach(s -> stringBuilder.append(s + ","));
            String subjectIdStr = stringBuilder.toString();
            subjectIdStr = subjectIdStr.substring(0, subjectIdStr.length() - 1);
            List<String> isExist = jdbcTemplate.queryForList("select 1 from tsinghua_formal_answer where subject_relation_id in (?) and ques_index is null LIMIT 0,1", new Object[]{subjectIdStr}, String.class);
//            if (CollectionUtil.isNotEmpty(isExist)){
//                jdbcTemplate.update("UPDATE \n" +
//                        "tsinghua_formal_answer a,dp_ques_index_mapping b \n" +
//                        "set \n" +
//                        "a.ques_index = b.ques_index, \n" +
//                        "a.right_answer = b.right_answer,\n" +
//                        "a.full_score = b.full_score\n" +
//                        "where a.ques_id = b.question_id");
//            }
            //检查穷举表
            //1.查题目数量是否正确
            String dp_ques_index_mappingC = jdbcTemplate.queryForObject("SELECT count(1) c from dp_ques_index_mapping where question_type in (1,2,3,6) and subject_relation_id in (?)", new Object[]{subjectIdStr}, String.class);
            String th_ques_score_mappingC = jdbcTemplate.queryForObject("select count(1) c from \n" +
                    "(SELECT 1 from th_ques_score_mapping where type in (1,2,3,6) and relation_subject_id in (?) GROUP BY ques_id) a", new Object[]{subjectIdStr}, String.class);
            if (!dp_ques_index_mappingC.equals(th_ques_score_mappingC)) {
                insertTsinghuaFormalAnswerErr("穷举表与dp_ques_index_mapping表group by后数据不一致,dp_ques_index_mapping数量:" + dp_ques_index_mappingC + "th_ques_score_mapping数量:" + th_ques_score_mappingC);
                process = 0f;
                SystemVariables.InterfaceSwitch = true;
                return;
            }
            //2.穷举可能性数量是否正确
            List<TsinghuaFormalAnswerVo> optionCounts = jdbcTemplate.query("SELECT question_id ques_id,count(1) count from sparta_paper_question_option GROUP BY question_id", new BeanPropertyRowMapper<>(TsinghuaFormalAnswerVo.class));
            Map<Long, Integer> optionMap = optionCounts.stream().collect(Collectors.toMap(TsinghuaFormalAnswerVo::getQuesId, TsinghuaFormalAnswerVo::getCount));
            List<TsinghuaFormalAnswerVo> qiongjuCounts = jdbcTemplate.query("SELECT ques_id,count(1) count from th_ques_score_mapping where type < 5 GROUP BY ques_id", new BeanPropertyRowMapper<>(TsinghuaFormalAnswerVo.class));
            Map<Long, Integer> qiongjuMap = qiongjuCounts.stream().collect(Collectors.toMap(TsinghuaFormalAnswerVo::getQuesId, TsinghuaFormalAnswerVo::getCount));
            StringBuilder qiongjuStr = new StringBuilder();
            for (Map.Entry<Long, Integer> entry : optionMap.entrySet()) {
                Long key = entry.getKey();
                Integer qiongjuNum = qiongjuMap.get(key);
                Integer optionNum = entry.getValue();
                Integer zuheNum = calculateSDcore(optionNum);
                if (!qiongjuNum.equals(zuheNum + 2)) {
                    qiongjuStr.append(entry.getKey() + "题号，穷举数量不对，穷举表数量：" + qiongjuNum + ",应该为：" + (zuheNum + 2) + ";");
                }
            }
            String s = qiongjuStr.toString();
            if (StrUtil.isNotBlank(s)) {
                insertTsinghuaFormalAnswerErr(s);
                process = 0f;
                SystemVariables.InterfaceSwitch = true;
                return;
            }
            //3.分值：查看答案穷举表分数是否有null
            List<String> test1 = jdbcTemplate.queryForList("SELECT 1 from th_ques_score_mapping where type in (1,2,3,6) and (score is null or REPLACE(score,' ','')  = '') and relation_subject_id in (?)", new Object[]{subjectIdStr}, String.class);
            if (CollectionUtil.isNotEmpty(test1)) {
                insertTsinghuaFormalAnswerErr("答案穷举表该科目有分数为空");
                process = 0f;
                SystemVariables.InterfaceSwitch = true;
                return;
            }
            process = 20f;
            //4.更新mq状态：查看exam_subject_student表是否有状态为1，如果有不执行
            List<String> mqStatus = jdbcTemplate.queryForList("SELECT 1 from sparta_exam_subject_student where mq_status = 1", String.class);
//            if (CollectionUtil.isEmpty(mqStatus)){
//                spotCheckAnswerService.updateMqType();
//            }
            //5.更新tsinghua_formal_score中来自日志的数据，将type为null的修改
            List<String> rzlist = jdbcTemplate.queryForList("SELECT 1 from tsinghua_formal_answer where answer_source = 1 and type is null", String.class);
//            if (CollectionUtil.isNotEmpty(rzlist)){
//                jdbcTemplate.update("UPDATE tsinghua_formal_answer a,dp_ques_index_mapping b\n" +
//                        "set a.type = b.question_type \n" +
//                        "where a.answer_source = 1 and a.ques_id = b.question_id");
//            }
            //查找有多少学科,按学科划分线程
//        int threadNum = subjectIds.length;
//        CountDownLatch countDownLatch = new CountDownLatch(threadNum);
//        ExecutorService executor = Executors.newFixedThreadPool(100);
//        if (threadNum>0){
//            for (String spartaSubject : subjectIds) {
//                Runnable task = new TsinghuaFormalAnswerController.MultithreadingOfCalculationScore(countDownLatch,spartaSubject);
//                // 执行
//                executor.execute(task);
//            }
//        }
//        countDownLatch.await(); //
//        executor.shutdown();//关闭线程池
            //死锁问题无法解决,先循环修改
            for (String subjectId : subjectIds) {
                //TODO 不考虑答案replace,可能需要改变
                //2021年5月28日新增,tsinghua_hormal_answer表会出现type=5的题,题型为主观题
                thQuesScoreMappingService.calculationScore(subjectId);
                process = process + 60 / subjectIds.length;
            }
            process = 85f;
            //最后修改填空题没有分数的题为0分
            // TODO 2021年5月28日新增,可能还要将主观题分数改为0,看后续需求
            int i = thQuesScoreMappingService.calculationScoreOfZero();
            process = 90f;
            //检查有没有学生没分数的存在
            List<String> list = jdbcTemplate.queryForList("SELECT 1 from tsinghua_formal_answer where type in (1,2,3,6) and score is null and subject_relation_id in (?)", new Object[]{subjectIdStr}, String.class);
            if (CollectionUtil.isNotEmpty(list)) {
                RedisErr redisErr = new RedisErr();
                redisErr.setMsg("tsinghua_formal_answer表有数据没更新到分数");
                redisErr.setCurrentTime(DateUtil.now());
                JSON parse = JSONUtil.parse(redisErr);
                redisTemplate.opsForSet().add(examUUID + "TsinghuaFormalAnswerErr", parse);
                for (String subject : subjectIds) {
                    redisTemplate.opsForHash().put(examUUID + "ProcessOf" + subject, "formalAnswer", "0");
                    redisTemplate.opsForHash().put(examUUID + "ProcessOf" + subject, "quesScore", "0");
                    redisTemplate.opsForHash().put(examUUID + "ProcessOf" + subject, "subjectScore", "0");
                }
                process = 0f;
                SystemVariables.InterfaceSwitch = true;
                return;
            }
            //单题是否超过总分的
            List<TsinghuaFormalAnswerVo> vos = jdbcTemplate.query("SELECT ques_id from tsinghua_formal_answer where score+0 > full_score+0 and type in (1,2,3,6) and subject_relation_id in (?) GROUP BY ques_id", new Object[]{subjectIdStr}, new BeanPropertyRowMapper<>(TsinghuaFormalAnswerVo.class));
            if (CollectionUtil.isNotEmpty(vos)) {
                RedisErr redisErr = new RedisErr();
                StringBuilder stringBuilder1 = new StringBuilder();
                vos.stream().forEach(v -> stringBuilder1.append(v.getQuesId() + ","));
                String s1 = stringBuilder1.toString();
                s1 = s1.substring(0, s1.length() - 1);
                redisErr.setMsg("tsinghua_formal_answer表有题目分大于该题总分,题号数量:" + vos.size() + ",题号:" + s1);
                redisErr.setCurrentTime(DateUtil.now());
                JSON parse = JSONUtil.parse(redisErr);
                redisTemplate.opsForSet().add(examUUID + "TsinghuaFormalAnswerErr", parse);
                for (String subject : subjectIds) {
                    redisTemplate.opsForHash().put(examUUID + "ProcessOf" + subject, "formalAnswer", "0");
                    redisTemplate.opsForHash().put(examUUID + "ProcessOf" + subject, "quesScore", "0");
                    redisTemplate.opsForHash().put(examUUID + "ProcessOf" + subject, "subjectScore", "0");
                }
                process = 0f;
                SystemVariables.InterfaceSwitch = true;
                return;
            }
            //同一题，同一个答案是否 出现不同分
            List<TsinghuaFormalAnswerVo> oneAnsTwoScore = jdbcTemplate.query("SELECT ques_id,answer,count(1) count from\n" +
                    "(SELECT ques_id,answer,score from tsinghua_formal_answer where subject_relation_id in (?) and type in (1,2,3,6) GROUP BY ques_id,answer,score) a GROUP BY ques_id,answer\n" +
                    "having count > 1", new Object[]{subjectIdStr}, new BeanPropertyRowMapper<>(TsinghuaFormalAnswerVo.class));
            if (CollectionUtil.isNotEmpty(oneAnsTwoScore)) {
                StringBuilder stringBuilder1 = new StringBuilder();
                oneAnsTwoScore.stream().forEach(v -> stringBuilder1.append("题号:" + v.getQuesId() + ",答案:" + v.getAnswer() + "/r/n"));
                String s1 = stringBuilder1.toString();
                insertTsinghuaFormalAnswerErr("tsinghua_formal_answer表有题目同一题 出现不同分," + s1);
                for (String subject : subjectIds) {
                    redisTemplate.opsForHash().put(examUUID + "ProcessOf" + subject, "formalAnswer", "0");
                    redisTemplate.opsForHash().put(examUUID + "ProcessOf" + subject, "quesScore", "0");
                    redisTemplate.opsForHash().put(examUUID + "ProcessOf" + subject, "subjectScore", "0");
                }
                process = 0f;
                SystemVariables.InterfaceSwitch = true;
                return;
            }
            //将该科目的redis算分状态改变
            for (String subjectId : subjectIds) {
                redisTemplate.opsForHash().put(examUUID + "ProcessOf" + subjectId, "formalAnswer", "1");
            }

        } catch (Exception e) {
            insertTsinghuaFormalAnswerErr("未知错误，请查看日志");
            process = 0f;
            SystemVariables.InterfaceSwitch = true;
            e.printStackTrace();
        }
        //计算时间:结束时间
        Instant insTwo = Instant.now();
        process = 100f;
        System.out.println("Difference in seconds(秒) : " + Duration.between(insOne, insTwo).getSeconds());
        //最后打开开关
        SystemVariables.InterfaceSwitch = true;
    }

    /**
     * 返回TsinghuaFormalAnswerErr
     */
    @GetMapping("/queryTsinghuaFormalAnswerErr")
    @ApiOperation("查询计算分值错误,有错误则返回错误列表,没错误则不返回data")
//    @PreAuthorize(hasRole = "admin")
    public AjaxResult queryTsinghuaFormalAnswerErr() {
        Boolean hasKey = redisTemplate.hasKey(examUUID + "TsinghuaFormalAnswerErr");
        if (hasKey) {
            Set members = redisTemplate.opsForSet().members(examUUID + "TsinghuaFormalAnswerErr");
            return AjaxResult.success(members);
        } else {
            return AjaxResult.success();
        }
    }

    /**
     * 返回是否可以执行
     */
    @GetMapping("/queryIsOk")
    @ApiOperation("查询是否可以执行,true可通行； false不可通行")
//    @PreAuthorize(hasRole = "admin")
    public AjaxResult queryProcessIsOk() {
        HashMap<String, Object> map = new HashMap<>();
        map.put("isOk", SystemVariables.InterfaceSwitch);
        map.put("msg", SystemVariables.msg);
        return AjaxResult.success(map);
    }

    /**
     * 返回TsinghuaFormalAnswerErr
     */
    public void insertTsinghuaFormalAnswerErr(String msg) {
        RedisErr redisErr = new RedisErr();
        redisErr.setMsg(msg);
        redisErr.setCurrentTime(DateUtil.now());
        JSON parse = JSONUtil.parse(redisErr);
        redisTemplate.opsForSet().add(examUUID + "TsinghuaFormalAnswerErr", parse);
    }

    /**
     * 返回更新score进度
     */
    @GetMapping("/updateScoreProcess")
    @ApiOperation("返回更新进度")
//    @PreAuthorize(hasRole = "admin")
    public AjaxResult updateScoreProcess() throws InterruptedException {
//        return AjaxResult.success(thQuesScoreMappingService.processOfUpdateScore());
        return AjaxResult.success(TsinghuaFormalAnswerController.process);
    }

    @GetMapping("/test")
    public AjaxResult test() throws InterruptedException {
        List<String> subjectIds = jdbcTemplate.queryForList("SELECT subject_id from dp_ques_score GROUP BY subject_id", String.class);
//        if (CollectionUtil.isNotEmpty(vos)){
//            StringBuilder stringBuilder1 = new StringBuilder();
//            vos.stream().forEach(v -> stringBuilder1.append(v.getId()+",") );
//            String s1 = stringBuilder1.toString();
//            s1=s1.substring(0,s1.length()-1);
//            return AjaxResult.success("tsinghua_formal_answer表有题目分大于该题总分,数量:"+vos.size()+",id:"+s1);
//        }
        for (String subject : subjectIds) {
            redisTemplate.opsForHash().put(examUUID + "ProcessOf" + subject, "formalAnswer", "1");
            redisTemplate.opsForHash().put(examUUID + "ProcessOf" + subject, "quesScore", "1");
            redisTemplate.opsForHash().put(examUUID + "ProcessOf" + subject, "subjectScore", "1");
        }
        return AjaxResult.success();
    }


    //---------------------------------------------------分割线--------------------------------------------------------------------------------------------------


    /**
     * 多线程之填空插入穷举表资源类
     */
    private class MultithreadingOfTianKongInsert implements Runnable {
        private CountDownLatch threadsSignal;

        public MultithreadingOfTianKongInsert(CountDownLatch threadsSignal) {
            this.threadsSignal = threadsSignal;
        }

        @Override
        public void run() {
            try {
                List<ThQuesScoreMapping> thQuesScoreMappingVos = new CopyOnWriteArrayList<>();
                for (int i = 0; i < 100; i++) {
                    if (tsinghuaFormalAnswerQueue.isEmpty()) {
                        break;
                    }
                    TsinghuaFormalAnswerVo vo = tsinghuaFormalAnswerQueue.poll();//消费-省

                    ThQuesScoreMapping scoreMapping = new ThQuesScoreMapping();
                    scoreMapping.setSubjectId(vo.getSubjectId());
                    scoreMapping.setRelationSubjectId(Long.parseLong(vo.getSubjectRelationId() + ""));
                    scoreMapping.setQuesId(vo.getQuesId());
                    scoreMapping.setQuesIndex(vo.getQuesIndex() + "");
                    //TODO 可能要换字段
                    scoreMapping.setAnswer(vo.getAnswer());
                    scoreMapping.setExamUuid(examUuid);
                    scoreMapping.setScore("0");
                    thQuesScoreMappingVos.add(scoreMapping);
                }

                if (thQuesScoreMappingVos.size() > 0) {
                    thQuesScoreMappingService.batchInsertThQuesScoreMapping(thQuesScoreMappingVos);
                }
                // 线程结束时计数器减1
                threadsSignal.countDown();//必须等核心处理逻辑处理完成后才可以减1
                log.info(Thread.currentThread().getName() + "结束. 还有" + threadsSignal.getCount() + " 个线程 ");
            } catch (Exception e) {
                insertTsinghuaFormalAnswerErr("未知错误，请查看日志");
                process = 0f;
                SystemVariables.InterfaceSwitch = true;
                e.printStackTrace();
            }
        }
    }

    /**
     * 多线程之计算score
     */
    private class MultithreadingOfCalculationScore implements Runnable {
        private CountDownLatch threadsSignal;
        private String subjectId;

        public MultithreadingOfCalculationScore(CountDownLatch threadsSignal, String subjectId) {
            this.threadsSignal = threadsSignal;
            this.subjectId = subjectId;
        }

        @Override
        public void run() {
            try {
                thQuesScoreMappingService.calculationScore(subjectId);
                // 线程结束时计数器减1
                threadsSignal.countDown();//必须等核心处理逻辑处理完成后才可以减1
                log.info(Thread.currentThread().getName() + "结束. 还有" + threadsSignal.getCount() + " 个线程 ");
            } catch (Exception e) {
                insertTsinghuaFormalAnswerErr("未知错误，请查看日志");
                process = 0f;
                SystemVariables.InterfaceSwitch = true;
                e.printStackTrace();
            }

        }
    }

    //计算穷举数量
    public int calculateSDcore(int n) {
        int result = 0;
        for (int i = 1; i <= n; i++) {
            result += MathUtil.combinationCount(n, i);
        }
        return result;
    }
}
